/**
 * Copyright (c) 2013 onionframework.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.onionframework.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.onionframework.core.components.ComponentDescriptor;
import org.onionframework.core.components.OptionalPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

@Component("core.framework")
public class Framework{

	private static Logger logger = LoggerFactory.getLogger(Framework.class);
	
	@Autowired private ApplicationContext applicationContext;
	
	private static Set<String> optionalParts = new HashSet<String>();
	
	private static SortedSet<ComponentDescriptor> components = new TreeSet<ComponentDescriptor>(new Comparator<ComponentDescriptor>(){
		@Override
		public int compare(ComponentDescriptor o1, ComponentDescriptor o2) {
			int result = o1.getOrder() - o2.getOrder();
			return result == 0 ? 1 : result;
		}
	});
	
	public static void loadComponents(){
		try {
			ComponentDescriptor component;
			Enumeration<URL> components = Framework.class.getClassLoader().getResources("META-INF/component.xml");
			URL url;
			XStream xstream;
			InputStream in;
			while(components.hasMoreElements()){
				url = components.nextElement();
				xstream = new XStream(new DomDriver());
				in = url.openStream();
				xstream.processAnnotations(ComponentDescriptor.class);
				component = (ComponentDescriptor) xstream.fromXML(in);
				component.init();
				
				logger.info("加载组件描述符:{}",url.toString());
				
				for(OptionalPart optional : component.getOptionalParts()){
					if(optionalParts.contains(optional.getId()))
						throw new RuntimeException("发现id冲突的可选部分：" + optional.getId());
					else
						optionalParts.add(optional.getId());
				}
				
				logger.info("发现了组件：{}:{}:{}[{}]",new Object[]{component.getGroupId(),component.getArtifactId(),component.getVersion(),component.getName()});
				
				Framework.registerComponent(component);
				
				in.close();
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
	public static void registerComponent(ComponentDescriptor component){
		components.add(component);
	}
	
	public static void optionalPartLoaded(String id, String[] resources){
		findOptionalPart(id).loaded(resources);
	}
	
	public static void optionalPartNotLoaded(String id, String[] resources){
		findOptionalPart(id).notLoaded(resources);
	}
	
	private static OptionalPart findOptionalPart(String id){
		for(ComponentDescriptor component : components){
			for(OptionalPart optional : component.getOptionalParts()){
				if(id.equals(optional.getId())){
					return optional;
				}
			}
		}
		
		return null;
	}
	
	public static SortedSet<ComponentDescriptor> getComponents(){
		return components;
	}
}
